package com.hospital.post.controller;

import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.core.type.TypeReference;
import com.hospital.common.base.PageResult;
import com.hospital.common.base.Result;
import com.hospital.common.base.ThreadAttributes;
import com.hospital.common.dto.message.module.AddMessageDto;
import com.hospital.common.dto.search.module.PostInsertDto;
import com.hospital.common.dto.search.module.ReplyInsertDto;
import com.hospital.common.utils.ThreadLocalUtils;
import com.hospital.post.dto.AddFloorDto;
import com.hospital.post.dto.AddPostDto;
import com.hospital.post.dto.AddReportDto;
import com.hospital.post.dto.AttachmentsDto;
import com.hospital.post.exception.ServiceException;
import com.hospital.post.feign.AuditFeign;
import com.hospital.post.feign.ESFeign;
import com.hospital.post.feign.HospitalFeign;
import com.hospital.post.feign.MessageFeign;
import com.hospital.post.service.PostService;
import com.hospital.post.utils.JsonUtils;
import com.hospital.post.vo.PostContentVo;
import com.hospital.post.vo.PostMetaVo;
import com.hospital.post.vo.SectionVo;
import jakarta.validation.constraints.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

import static com.hospital.post.exception.enums.ExceptionCode.FORBIDDEN;
import static com.hospital.post.exception.enums.ExceptionCode.NOT_FOUND;

/**
 * 帖子相关接口
 */
@RestController
@RequestMapping("/post")
public class PostController
{
    private final Integer SUB_POST_PAGESIZE = 8;

    @Autowired
    private PostService postService;
    @Autowired
    private HospitalFeign hospitalFeign;
    @Autowired
    private MessageFeign messageFeign;
    @Autowired
    private AuditFeign auditFeign;
    @Autowired
    private ESFeign esFeign;


    /**
     * 获取所有板块
     * @return 板块对象列表
     */
    @GetMapping("/getAllSections")
    public Result getAllSections()
    {
        List<SectionVo> sections = postService.getAllSections();
        return Result.success(sections);
    }

    /**
     * 获取板块内帖子
     * @param sectionId 板块id |1
     * @param pinnedOnly 是否只显示精华帖（是则传入1） |0
     * @param pageNum 页码 |1
     * @param pageSize 每页大小 |10
     * @return 帖子元数据对象分页列表
     */
    @GetMapping("/getPosts")
    public Result getPosts(@RequestParam("sectionId") @NotNull(message = "板块id不能为空") Long sectionId,
                           @RequestParam(value = "pinnedOnly",required = false,defaultValue = "0") Integer pinnedOnly,
                           @RequestParam("pageNum") @NotNull(message = "页码不能为空") Integer pageNum,
                           @RequestParam("pageSize") @NotNull(message = "页大小不能为空") Integer pageSize)
    {
        Integer count = postService.getPostCount(sectionId,pinnedOnly);
        if(count == 0){
            return Result.success();
        }
        List<PostMetaVo> posts = postService.getPosts(sectionId,pinnedOnly,pageNum,pageSize);
        return Result.success(new PageResult<>((long) count, posts));
    }

    /**
     * 获取帖子详情
     * @param metaId 帖子id |1
     * @param LZOnly 是否只显示楼主（是的话此处传入楼主ID） |0
     * @param pageNum 页码 |1
     * @param pageSize 每页大小 |10
     * @return 帖子内容对象（楼层）分页列表
     */
    @GetMapping("/getPostDetail")
    public Result getPostDetail(@RequestParam("metaId") @NotNull(message = "帖子id不能为空") Long metaId,
                                @RequestParam(value = "LZOnly",defaultValue = "0") Long LZOnly,
                                @RequestParam("pageNum") @NotNull(message = "页码不能为空") Integer pageNum,
                                @RequestParam("pageSize") @NotNull(message = "页大小不能为空") Integer pageSize)
    {
        Integer count = postService.getPostDetailCount(metaId,LZOnly);
        if(count == 0){
            return Result.fail("帖子不存在");
        }
        List<PostContentVo> posts = postService.getPostDetail(metaId,pageNum,pageSize,SUB_POST_PAGESIZE,LZOnly);
        return Result.success(new PageResult<>((long) count, posts));
    }

    /**
     * 获取楼层
     * @param floorId 楼层id |1
     * @return 帖子内容对象（楼层）含楼中楼
     */
    @GetMapping("/getFloor")
    public Result getReply(@RequestParam("floorId") @NotNull(message = "楼层id不能为空") Long floorId)
    {
        PostContentVo floor = postService.getFloor(floorId,SUB_POST_PAGESIZE);
        return Result.success(floor);
    }

    /**
     * 获取楼中楼
     * @param floorId 楼层id |1
     * @param pageNum 页码 |1
     * @param pageSize 每页大小 |10
     * @return 楼中楼对象分页列表
     */
    @GetMapping("/getSubPosts")
    public Result getSubPosts(@RequestParam("floorId") @NotNull(message = "楼层id不能为空") Long floorId,
                               @RequestParam("pageNum") @NotNull(message = "页码不能为空") Integer pageNum,
                               @RequestParam("pageSize") @NotNull(message = "页大小不能为空") Integer pageSize){
        Integer count = postService.getSubPostCount(floorId);
        if(count == 0){
            return Result.success();
        }
        List<PostContentVo> posts = postService.getSubPosts(floorId,pageNum,pageSize);
        return Result.success(new PageResult<>((long) count, posts));
    }

    /**
     * 发帖
     * @param addPostDto 发帖对象
     * @return 发帖成功
     */
    @PostMapping("/addPost")
    public Result addPost(@RequestBody @Validated AddPostDto addPostDto){
        ThreadAttributes ta = ThreadLocalUtils.get();
        if(ta==null){
            throw new ServiceException(FORBIDDEN);
        }
        Long authorId = ta.getUserId();
        Integer authorRole = ta.getRoleType();

        //人员校验
        if(auditFeign.getBannedStatus(addPostDto.getSectionId(),authorId).getData()==1){
            throw new ServiceException(FORBIDDEN,"该账户已被封禁");
        }

        //数据敏感词校验
        if(auditFeign.getViolation(addPostDto.getText()).getData()==-1){
            throw new ServiceException(FORBIDDEN,"内容违规");
        }

        //帖子附件校验
        if(StringUtils.hasLength(addPostDto.getAttachments())){
            List<AttachmentsDto> tmpAttachments = new ArrayList<>();
            //List<AttachmentsDto> attachments = JsonUtils.parse(addPostDto.getAttachments(),List.class);
            List<AttachmentsDto> attachments = JSONUtil.toList(addPostDto.getAttachments(),AttachmentsDto.class);
            for(AttachmentsDto attachment:attachments){
                if(StringUtils.hasLength(attachment.getUrl()) && addPostDto.getHtml().contains(attachment.getUrl())){
                    tmpAttachments.add(attachment);
                }else{
                    //删除多余附件
                    hospitalFeign.deleteFile(attachment.getFilePath());
                }
            }
            addPostDto.setAttachments(JsonUtils.toJson(tmpAttachments));
        }

        //发帖
        Long metaId=postService.addPost(addPostDto,authorId,authorRole);

        //插入ES
        PostInsertDto postInsertDto = PostInsertDto.builder()
                .metaId(metaId)
                .sectionId(addPostDto.getSectionId())
                .authorId(authorId)
                .title(addPostDto.getTitle())
                .abstracts(addPostDto.getText())
                .isTop(0)
                .isPinned(0)
                .likeCount(0)
                .replyCount(0)
                .createTime(LocalDateTime.now())
                .updateTime(LocalDateTime.now())
                .favoriteCount(0)
                .firstAttachmentUrl(addPostDto.getAttachments())
                .heatScore(0L)
                .authorRole(authorRole)
                .build();
        esFeign.insertPost(postInsertDto);

        return Result.success("发帖成功");
    }

    /**
     * 回复帖子
     * @param addFloorDto 回复内容对象
     * @return 回复成功
     */
    //@SuppressWarnings("unchecked")
    @PostMapping("/addFloor")
    public Result addFloor(@RequestBody @Validated AddFloorDto addFloorDto){
        ThreadAttributes ta = ThreadLocalUtils.get();
        if(ta==null){
            throw new ServiceException(FORBIDDEN);
        }
        Long authorId = ta.getUserId();
        Integer authorRole = ta.getRoleType();

        //人员校验
        Long sectionId = postService.getSectionIdByMetaId(addFloorDto.getMetaId());
        if(sectionId== null){
            throw new ServiceException(NOT_FOUND,"帖子不存在");
        }
        if(auditFeign.getBannedStatus(sectionId,authorId).getData()==1){
            throw new ServiceException(FORBIDDEN,"该账户已被封禁");
        }

        //数据敏感词校验
        if(auditFeign.getViolation(addFloorDto.getText()).getData()==-1){
            throw new ServiceException(FORBIDDEN,"内容违规");
        }

        //楼中楼校验
        if(addFloorDto.getRepliedId()!=0){
            addFloorDto.setHtml(addFloorDto.getText());
        }

        //帖子附件校验
        if(StringUtils.hasLength(addFloorDto.getAttachments())){
            List<AttachmentsDto> tmpAttachments = new ArrayList<>();
            List<AttachmentsDto> attachments = JsonUtils.parse(addFloorDto.getAttachments(),new TypeReference<>(){});
            for(AttachmentsDto attachment:attachments){
                if(StringUtils.hasLength(attachment.getUrl()) && addFloorDto.getHtml().contains(attachment.getUrl())){
                    tmpAttachments.add(attachment);
                }else{
                    //删除多余附件
                    hospitalFeign.deleteFile(attachment.getFilePath());
                }
            }
            addFloorDto.setAttachments(JsonUtils.toJson(tmpAttachments));
        }


        //回帖
        Long floorId =postService.addFloor(addFloorDto,authorId,authorRole);

        //发消息给被回复者
        AddMessageDto addMessageDto =AddMessageDto.builder()
                .senderId(authorId)
                .receiverId(addFloorDto.getTargetId())
                .messageContent(addFloorDto.getText())
                .metaId(addFloorDto.getMetaId())
                .contentId(floorId)
                .messageType(2)
                .build();
        messageFeign.addMessage(addMessageDto);

        //向es中插入回帖
        ReplyInsertDto replyInsertDto = ReplyInsertDto.builder()
                .metaId(addFloorDto.getMetaId())
                .contentId(floorId)
                .text(addFloorDto.getText())
                .build();
        esFeign.insertReply(replyInsertDto);

        return Result.success("回帖成功");
    }

    /**
     * 获取帖子是否已点赞
     * @param metaId 帖子id |1
     * @return 帖子是否已点赞
     */
    @GetMapping("/getHasLiked")
    public Result getHasLiked(@RequestParam("metaId") @NotNull(message = "帖子id不能为空") Long metaId){
        ThreadAttributes ta = ThreadLocalUtils.get();
        if(ta==null){
            throw new ServiceException(FORBIDDEN);
        }
        Long userId = ta.getUserId();

        if(!postService.getHasLiked(userId,metaId)){
            return Result.success(false);
        }
        return Result.success(true);
    }

    /**
     * 获取帖子是否已收藏
     * @param metaId 帖子id |1
     * @return 帖子是否已收藏
     */
    @GetMapping("/getHasBeenFavorite")
    public Result getHasBeenFavorite(@RequestParam("metaId") @NotNull(message = "帖子id不能为空") Long metaId){
        ThreadAttributes ta = ThreadLocalUtils.get();
        if(ta==null){
            throw new ServiceException(FORBIDDEN);
        }
        Long userId = ta.getUserId();

        if(!postService.getHasBeenFavorite(userId,metaId)){
            return Result.success(false);
        }
        return Result.success(true);
    }

    /**
     * 点赞
     * @param metaId 帖子id |1
     * @param like 1点赞 0取消
     * @return 操作成功
     */
    @GetMapping("/addLike")
    public Result addLike(@RequestParam("metaId") @NotNull(message = "帖子id不能为空") Long metaId,
                          @RequestParam("like") @NotNull(message = "点赞不能为空") Integer like){
        ThreadAttributes ta = ThreadLocalUtils.get();
        if(ta==null){
            throw new ServiceException(FORBIDDEN);
        }
        Long userId = ta.getUserId();

        if(!postService.addLike(userId,metaId, like)){
            return Result.fail("操作失败");
        }
        return Result.success("操作成功");
    }

    /**
     * 收藏
     * @param metaId  帖子id |1
     * @param favorite 1收藏 0取消
     * @return 操作成功
     */
    @GetMapping("/addFavorite")
    public Result addFavorite(@RequestParam("metaId") @NotNull(message = "帖子id不能为空") Long metaId,
                          @RequestParam("favorite") @NotNull(message = "收藏不能为空") Integer favorite){
        ThreadAttributes ta = ThreadLocalUtils.get();
        if(ta==null){
            throw new ServiceException(FORBIDDEN);
        }
        Long userId = ta.getUserId();

        if(!postService.addFavorite(userId,metaId, favorite)){
            return Result.fail("操作失败");
        }
        return Result.success("操作成功");
    }

    /**
     * 获取收藏帖子列表
     * @param pageNum 页码 |1
     * @param pageSize 页大小 |10
     * @return 收藏帖子元数据对象分页列表
     */
    @GetMapping("/getFavorites")
    public Result getFavorites(@RequestParam("pageNum") @NotNull(message = "页码不能为空") Integer pageNum,
                               @RequestParam("pageSize") @NotNull(message = "页大小不能为空") Integer pageSize)
    {
        ThreadAttributes ta = ThreadLocalUtils.get();
        if(ta==null){
            throw new ServiceException(FORBIDDEN);
        }
        Long userId = ta.getUserId();

        Integer FavoritesCount = postService.getFavoritesCount(userId);
        if(FavoritesCount==0){
            return Result.success(null);
        }
        List<PostMetaVo> posts = postService.getFavorites(userId,pageNum,pageSize);

        return Result.success(new PageResult<>((long)FavoritesCount,posts));

    }


    /**
     * （作者）删除帖子
     * @param metaId 帖子id |1
     * @return 删除成功
     */
    @DeleteMapping("/deletePost")
    public Result deletePost(@RequestParam("metaId") @NotNull(message = "帖子id不能为空") Long metaId){
        ThreadAttributes ta = ThreadLocalUtils.get();
        if(ta==null){
            throw new ServiceException(FORBIDDEN);
        }
        Long userId = ta.getUserId();

        Long authorId = postService.getAuthorIdByMetaId(metaId);
        if(authorId==null||!authorId.equals(userId)){
            throw new ServiceException(FORBIDDEN);
        }
        if(postService.deletePost(metaId,userId)==0){
            return Result.fail("删除失败");
        }
        return Result.success("删除成功");
    }

    /**
     * （作者）删除帖子楼层
     * @param floorId 楼层id |1
     * @return 删除成功
     */
    @DeleteMapping("/deleteFloor")
    public Result deleteFloor(@RequestParam("floorId") @NotNull(message = "楼层id不能为空") Long floorId){
        ThreadAttributes ta = ThreadLocalUtils.get();
        if(ta==null){
            throw new ServiceException(FORBIDDEN);
        }
        Long userId = ta.getUserId();

        Long authorId = postService.getAuthorIdByFloorId(floorId);
        if(authorId==null||!authorId.equals(userId)){
            throw new ServiceException(FORBIDDEN);
        }
        if(postService.deleteFloor(floorId,userId)==0){
            return Result.fail("删除失败");
        }
        return Result.success("删除成功");
    }

    /**
     * 举报
     * @param addReportDto 举报信息对象
     * @return 举报成功
     */
    @PostMapping("/addReport")
    public Result addReport(@RequestBody @Validated AddReportDto addReportDto){
        ThreadAttributes ta = ThreadLocalUtils.get();
        if(ta==null){
            throw new ServiceException(FORBIDDEN);
        }
        Long userId = ta.getUserId();

        if(!postService.addReport(addReportDto,userId)){
            return Result.fail("举报录入失败");
        }

        return Result.success("举报成功");
    }

    /**
     * 获取作者的帖子列表
     * @param pageNum 页码 |1
     * @param pageSize 页大小 |10
     * @return 帖子元数据对象分页列表
     */
    @GetMapping("/getMyPosts")
    public Result getMyPosts(@RequestParam("pageNum") @NotNull(message = "页码不能为空") Integer pageNum,
                             @RequestParam("pageSize") @NotNull(message = "页大小不能为空") Integer pageSize){
        ThreadAttributes ta = ThreadLocalUtils.get();
        if(ta==null){
            throw new ServiceException(FORBIDDEN);
        }
        Long userId = ta.getUserId();

        Integer myPostsCount = postService.getMyPostsCount(userId);
        if(myPostsCount==0){
            return Result.success();
        }
        List<PostMetaVo> posts = postService.getMyPosts(userId,pageNum,pageSize);
        return Result.success(new PageResult<>((long)myPostsCount,posts));
    }

    /**
     * 获取作者的回复列表
     * @param pageNum 页码 |1
     * @param pageSize 页大小 |10
     * @return 楼层对象分页列表
     */
    @GetMapping("/getMyReplies")
    public Result getMyReplies(@RequestParam("pageNum") @NotNull(message = "页码不能为空") Integer pageNum,
                             @RequestParam("pageSize") @NotNull(message = "页大小不能为空") Integer pageSize){
        ThreadAttributes ta = ThreadLocalUtils.get();
        if(ta==null){
            throw new ServiceException(FORBIDDEN);
        }
        Long userId = ta.getUserId();

        Integer myRepliesCount = postService.getMyRepliesCount(userId);
        if(myRepliesCount==0){
            return Result.success();
        }
        List<PostContentVo> posts = postService.getMyReplies(userId,pageNum,pageSize);
        return Result.success(new PageResult<>((long)myRepliesCount,posts));
    }

}
